﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Xml.Serialization;

namespace Bambit.XmlRpc
{
	/// <summary>
	///  One of two possible roots, method call is what is sent to the RPC server.  it consists
	/// strictly of the method name and the parameters associated with it.
	/// </summary>
	[Serializable]
	[XmlType(AnonymousType = true)]
	[XmlRoot("methodCall", IsNullable = false)]
	public class MethodCall
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="MethodCall"/> class.
		/// </summary>
		public MethodCall()
		{
			Parameters = new List<Parameter>();
		}

		/// <summary>
		/// Gets or sets the name of the method.
		/// </summary>
		/// <value>The name of the method that is being executed.</value>
		[XmlElement("methodName")]
		public string MethodName { get; set; }

		/// <summary>
		/// Gets or sets the parameter collection.
		/// </summary>	
		/// <value>The parameters for the method being exexcuted.</value>
		/// <remarks>This property is to ease implementation of XmlSerialization unt</remarks>
		[XmlArray("params")]
		[XmlArrayItem("param")]
		public List<Parameter> Parameters { get; set; }

		/// <summary>
		/// Executes the method call against the supplied URI
		/// </summary>
		/// <param name="uri">The URI of the Xml Rpc server.</param>
		/// <returns>A <see cref="MethodResponse"/> received from the remote server.</returns>
		/// <exception cref="WebException">The remote server did NOT supply a valid status code</exception>
		public MethodResponse Execute(string uri)
		{
			//System.Net.ServicePointManager.Expect100Continue = false;
			HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(uri);
			webRequest.UserAgent = "Bambit.XmlRpc.Consumer/0.1";
			webRequest.ContentType = "text/xml";
			StringWriter stringWriter=new StringWriter();
			XmlSerializer xmlSerializer=new XmlSerializer(typeof(MethodCall));
			xmlSerializer.Serialize(stringWriter, this);
			byte[] buffer = Encoding.ASCII.GetBytes(stringWriter.ToString());
			webRequest.ContentLength = buffer.Length;
			webRequest.Method = "POST";
			Stream requestStream = webRequest.GetRequestStream();
			requestStream.Write(buffer, 0, buffer.Length);
			requestStream.Close();

			MethodResponse methodResponse;
			using (HttpWebResponse httpWebResponse = (HttpWebResponse)webRequest.GetResponse())
			{
				if (httpWebResponse.StatusCode != HttpStatusCode.OK)
					throw new WebException("The remote server did not retuen success", null, WebExceptionStatus.UnknownError,
					                       httpWebResponse);

				XmlSerializer deserializer = new XmlSerializer(typeof (MethodResponse));
				//	For some reason I have yet to figure out, if I try to deserialize straight from the response
				//	stream, it throws an error about Unicode, but if I dump it to string first it works fine,
				//	so this is a pseudo hack
				StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream());
				string response = streamReader.ReadToEnd();
				methodResponse = (MethodResponse) deserializer.Deserialize(new StringReader(response));
			}
			return methodResponse;
		}
	}

	

	
	
}
